#include <iostream>
#include <memory>
#include <string>
#include <future>
#include <vector>
#include <chrono>
#include <unistd.h>  // 在gcc编译器中，使用的头文件因gcc版本的不同而不同，延时库
using SptrFlag = std::shared_ptr<std::atomic<bool>>;
using SptrImuData = std::vector<std::atomic<double>>;
using Vector_at = std::vector<std::atomic<double>>;
using HighResolutionTime = std::chrono::_V2::system_clock::time_point;  //= std::chrono::high_resolution_clock::now(); //计时用
int func(int x);
int func1(int x);
int imu_s(const SptrFlag& flag_sp);        // 模拟发送imu数据 200Hz,5ms一次
// template<typename T>
// int imu_s(T&& flag_sp);  // 万能引用版本，还不成熟
int calculat_imu(const SptrFlag& flag_sp);  // imu数据结算
class Man{
public:
    std::string name;
    int age;
    Man(){}
    Man(std::string name, int age);
    void printman();
    int run(const SptrFlag& flag_sp);
};
struct ImuData{
    SptrFlag flag;
    Vector_at imu_data;
    // TODO 时间戳
    HighResolutionTime time;// = std::chrono::high_resolution_clock::now(); //计时用
    ImuData(): imu_data(6), flag(std::make_shared<std::atomic<bool>>(false)){}
};
// load 用于读取 std::atomic 对象的值
// store操作用于将一个值存储到原子变量中，也是一个原子操作
std::atomic<int> ai(0); // 用于多线程访问的数据，并且不用互斥量，因为对于它的每一次操作都是原子操作，意思就是不可拆分的操作，所以不用担心多个线程同时操作这个数据

std::vector<std::atomic<double>> imu_data(6);


// std::atomic<std::string> dd("1.0");  // true时处理数据imu_data

int main(int, char**){
    // auto now = std::chrono::system_clock::now();
    // std::cout<<now<<"\n";
    std::cout<<"\nHello, from async API!\n";
    // std::cout<<dd.is_lock_free()<<std::endl;
    // std::atomic<bool> flag(false);  // true时处理数据imu_data
    SptrFlag flag_sp(std::make_shared<std::atomic<bool>>(false));
    std::cout << "flag_sp use_count: " << flag_sp.use_count() << std::endl;
    for(int i=0;i<6;i++){
        imu_data[i].store(i);//将一个值存储到原子变量中
    }
    // imu_data.clear();
    // std::cout << "Size: " << imu_data.size() << std::endl;
    // std::cout << "Capacity: " << imu_data.capacity() << std::endl;
    // auto itera_b = imu_data.begin();
    // auto itera_e = imu_data.end();
    // std::cout << "num: " << *(itera_b+2047 ) << std::endl;
    // std::cout << "num: " << *(itera_e) << std::endl;



    // imu_data.clear();

    // imu_data.emplace_back(1.0);
    // imu_data.push_back(1.0);

    // std::cout << "v[2]: " << imu_data[2] << std::endl;  // 输出 30
    // 启动方式
    // auto fut = std::async(std::launch::async,func,18);      // std::launch::async，异步方式启动func
    // auto fut = std::async(std::launch::deferred,func,18);   // std::launch::deferred，推迟方式启动func，只有在需要时才执行
    // 死等 fut.wait()
    // 定时等待
    // auto status = fut.wait_for(std::chrono::seconds(4));
    // if (status == std::future_status::ready) {
    //     std::cout << "Task completed. Result: " << fut.get() << std::endl;
    // } else if (status == std::future_status::timeout) {
    //     std::cout << "Task did not finish within the timeout." << std::endl;
    // } else if (status == std::future_status::deferred){
    //     std::cout << "Task was deferred." << std::endl;
    // }
    // else{
    //     std::cout << "else" << std::endl;
    // }


    // auto x = fut.get();     // 等待函数运行结束获取返回值，.get()方法只能调用一次
    // std::cout<<"返回结果是: "<<x<<std::endl;
    // auto fut1 = std::async(std::launch::async,func1,11);      // std::launch::async，异步方式启动func
    Man Qing("清清",20);
    auto fut2 = std::async(std::launch::async,imu_s, std::ref(flag_sp));      // std::launch::async，异步方式启动func
    auto fut3 = std::async(std::launch::async,calculat_imu, std::ref(flag_sp));      // std::launch::async，异步方式启动func
    // 如果使用非静态的成员函数作为启动函数，就不可以直接写，可以用std::bind(&Man::run, Qing, std::ref(flag_sp))绑定对象
    // 也可以用lambda表达式来显式捕获Qing对象，并调用其成员函数，这是现代 C++ 中推荐的做法，因为它更简洁且不依赖 std::bind
    auto fut4 = std::async(std::launch::async,[&Qing,&flag_sp](){
        return Qing.run(flag_sp);
    });      // std::launch::async，异步方式启动func
    while(1)
    {
        sleep(1);
        std::cout<<"ai: "<<ai<<std::endl;
    }
  

}

int imu_s(const SptrFlag& flag_sp){        // 模拟发送imu数据 200Hz,5ms一次
    auto sptr_flag_imu(flag_sp);
    std::cout << "imus flag_sp use_count: " << flag_sp.use_count() << std::endl;
    std::cout << "sptr_flag_imu use_count: " << sptr_flag_imu.use_count() << std::endl;
    int c = 0;
    while(1){
        usleep(5000);   //microseconds 微秒
        for(int i=0;i<6;i++){
            imu_data[i].store(i+c);
        }
        c++;
        flag_sp->store(true);
    }
}
int calculat_imu(const SptrFlag& flag_sp){  // imu数据结算
    auto sptr_flag_imu(flag_sp);
    std::cout << "calculat_imu flag_sp use_count: " << flag_sp.use_count() << std::endl;
    std::cout << "sptr_flag_imu use_count: " << sptr_flag_imu.use_count() << std::endl;
    // sleep(30);
    while(1){
        auto start = std::chrono::high_resolution_clock::now(); //计时用
        while(flag_sp->load() == false){
            std::this_thread::sleep_for(std::chrono::microseconds(300));
        }
        auto end = std::chrono::high_resolution_clock::now();
        // auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
        auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
        std::cout << "耗时: " << duration.count() << " 微秒" << std::endl;
        std::cout<<"imu_data: [ ";
        for(int i=0;i<6;i++){
            std::cout<<imu_data[i]<<" ";
        }
        std::cout<<" ]\n";
        flag_sp->store(false);
        
        
        
    }

}

Man::Man(std::string name, int age):name(name),age(age)
{std::cout<<"man has been created\n";}
void Man::printman()
{
    std::cout<<"name: "<<name<<" age:"<<age<<std::endl;
}
int Man::run(const SptrFlag& flag_sp){
    auto sptr_flag_imu(flag_sp);
    while(1){
        sleep(1);
        std::cout<<"进入run\n";
    }
}

int func(int x)
{
    auto upm(std::make_unique<Man>("毛利兰",18));
    upm->printman();
    
    // sleep(3);
    // return x;
    while(1)
    {
        sleep(1);
        upm->printman();
        ai++;
    }
    
}
int func1(int x)
{
    auto upm(std::make_unique<Man>("柯南",10));
    upm->printman();
    while(1)
    {
        sleep(4);
        upm->printman();
        ai++;
    }
    
}